/*
 * user_ui.c
 *
 *  Created on: 2021年2月24日
 *      Author: Jiarun
 */
#include "user_ui.h"
#include "module_init.h"
#include "zf_ccu6_pit.h"

#define DebounceTime 80u


PIN_enum KEY_Pin[5] = {P02_6, P02_8, P02_7, P02_4, P02_5};
int8 cousor_home = 0, cousor_sub = 0;
extern Param global_param;
KEY_value key_dir = KEY_NULL;

/*** 参数存取 ***/
uint8 first_load = 1;
void Param_load(){
    uint8 size = 0;
    uint32 flash_buf[15];

    size = sizeof(global_param) / 4;
    if(sizeof(global_param) % 4)
        size++;

    for(uint8 i = 0; i < size; i++){
        flash_buf[i] = flash_read(11, i, uint32);
    }
    memcpy(&global_param, flash_buf, sizeof(global_param));

    if(gpio_get(KEY_Pin[4]) == 0 && first_load){
        buzzing_ms(500);
        lcd_showstr(24, 3, "Skip reading...");
        while(!gpio_get(KEY_Pin[4]));
    }
}

void Param_sto(){
    uint8 size = 0;
    uint32 flash_buf[15];

    memcpy(flash_buf, &global_param, sizeof(global_param));

    size = sizeof(global_param) / 4;
    if(sizeof(global_param) % 4)
        size++;

    eeprom_erase_sector(11);
    for(uint8 i = 0; i < size; i++){
        eeprom_page_program(11, i, &flash_buf[i]);
    }
}

void Cancel_save(){
    uint8 save_flag = 0, point;

    while(TRUE){
        lcd_showchar(0,cousor_sub*16,' ');
        lcd_showchar(96,cousor_sub*16,' ');

        if(save_flag)
            point = 0;
        else
            point = 96;
        lcd_showchar(point,cousor_sub*16,'>');

        key_dir = KEY_NULL;
        while( !(key_dir = key_get()) );

        if(KEY_L == key_dir || KEY_R == key_dir)
            save_flag = !save_flag;
        else if(KEY_U == key_dir || KEY_D == key_dir)
            continue;
        else if(KEY_M == key_dir){
            return;
        }
    }
}

void buzzing_ms(uint16 buzzingTime){
    gpio_set(P33_5,1);
    systick_delay_ms(STM0, buzzingTime);
    gpio_set(P33_5,0);
}

/*** 按键初始化及获取 ***/
void key_init(){
    for(uint8 i=0; i<5; i++){
        gpio_init(KEY_Pin[i], GPI, 1, PUSHPULL);
    }
}

KEY_value key_get(){

    if(gpio_get(KEY_Pin[0]) == 0){
        systick_delay_ms(STM0, DebounceTime);
        if(gpio_get(KEY_Pin[0]) == 0){
            buzzing_ms(20);
            return KEY_U;
        }

    }

    else if(gpio_get(KEY_Pin[1]) == 0){
        systick_delay_ms(STM0, DebounceTime);
        if(gpio_get(KEY_Pin[1]) == 0){
            buzzing_ms(20);
            return KEY_D;
        }
    }

    else if(gpio_get(KEY_Pin[2]) == 0){
        systick_delay_ms(STM0, DebounceTime);
        if(gpio_get(KEY_Pin[2]) == 0){
            buzzing_ms(20);
            return KEY_L;
        }
    }

    else if(gpio_get(KEY_Pin[3]) == 0){
        systick_delay_ms(STM0, DebounceTime);
        if(gpio_get(KEY_Pin[3]) == 0){
            buzzing_ms(20);
            return KEY_R;
        }
    }

    else if(gpio_get(KEY_Pin[4]) == 0){
        systick_delay_ms(STM0, DebounceTime);
        if(gpio_get(KEY_Pin[4]) == 0){
            buzzing_ms(20);
            return KEY_M;
        }
    }

    return KEY_NULL;
}

extern uint8 junction;
void show_img(){
    /* 显示图像 */
    lcd_displayimg(2,2,Image_Use[0], USEW, USEH);
    lcd_displayBinimg(2,66,Bin_Image[0], USEW, USEH);

    /* 标记边线 */
    for(uint8 row = 5; row < 50; row++){
        if(!brim_L[row] && brim_R[row] < 0){
            continue;
        }

        if(brim_L[row]){
            lcd_drawpoint(brim_L[row] + 2, 125 - row, RED);
        }
        if(brim_R[row] > 0){
            lcd_drawpoint(brim_R[row] + 2, 125 - row, BLUE);
        }
        if(center[row] > 0 && row < val_row)
            lcd_drawpoint(center[row] + 2, 125 - row, GREEN);
    }/* end for */

    lcd_showuint8(128,0,row_cnt);
    lcd_showint8(128,1,(int8)bias);
    lcd_showuint8(104,2,valid_rowL);
    lcd_showuint8(136,2,valid_rowR);
    lcd_showuint8(128,4,crossroad_flag);
    lcd_showuint8(128,5,road_flag);
    lcd_showuint8(128,6,junction);
    lcd_showuint16(104,7,distance);

    lcd_showint16(104,3,GET_CFG[EXP_TIME-1][1]);
}


void img_display(){
    uint8 view_line = 0;

    debug_flag = 1;
    stopcar |= 0x80;
    pit_enable_interrupt(CCU6_1, PIT_CH0);
    pit_enable_interrupt(CCU6_0, PIT_CH0);

    lcd_clear(BLACK);
    lcd_showstr(114, 0, "|:");
    lcd_showstr(100, 1, "Err");

    lcd_showstr(114, 4, "+:");
    lcd_showstr(114, 5, "O:");
    lcd_showstr(114, 6, "Y:");

    key_dir = KEY_NULL;
    while(KEY_L != key_dir){

        key_dir = key_get();

        if(KEY_R == key_dir)
            view_line = !view_line;
        else if(KEY_U == key_dir){
            GET_CFG[EXP_TIME-1][1] += 5;
            GET_CFG[EXP_TIME-1][1] = set_exposure_time(MT9V03X_COF_UART, GET_CFG[EXP_TIME-1][1]);
        }
        else if(KEY_D == key_dir){
            GET_CFG[EXP_TIME-1][1] -= 5;
            GET_CFG[EXP_TIME-1][1] = set_exposure_time(MT9V03X_COF_UART, GET_CFG[EXP_TIME-1][1]);
        }else if(KEY_M == key_dir){

            MT9V03X_CFG[EXP_TIME-1][1] = GET_CFG[EXP_TIME-1][1];
            set_config(MT9V03X_COF_UART, MT9V03X_CFG);
            return;
        }


        if(mt9v03x_finish_flag)
            show_img();

        if(view_line){
            for(uint8 x = 0; x < USEW; x++){
                for(uint8 y = 0; y < USEH; y += 10){
                    lcd_drawpoint(x+2, y+2, RED);
                }
            }
            for(uint8 x = 0; x < USEW; x += 10){
                for(uint8 y = 0; y < USEH; ++y){
                    lcd_drawpoint(x+2, y+2, RED);
                }
            }
        }
    }
}


KEY_value cursor_show(int8* cursor, uint8 vul_max){

    while(TRUE){
        for (uint8 y=0; y< (vul_max + 1)*16; y++)
            for (uint8 x=0;x<8;x++)
                lcd_drawpoint(x,y,BLACK);
        lcd_showchar(0,*cursor*16,'>');

        key_dir = KEY_NULL;
        while( !(key_dir = key_get()) );

        if(KEY_U == key_dir){
            *cursor -= 1;
            if(*cursor < 0)
                *cursor = vul_max;
        }
        else if(KEY_D == key_dir){
            *cursor += 1;
            if(*cursor > vul_max)
                *cursor = 0;
        }

        else if(KEY_L == key_dir){
            return KEY_L;
        }
        else if(KEY_R == key_dir){
            return KEY_R;
        }
        else if(KEY_M == key_dir)
            return KEY_M;
    }
}

void ui_ParametSet(){
    int8 lcd_buf[6];

    lcd_clear(BLACK);
    lcd_showstr(16,0,"Level:");
    lcd_showstr(16,1,"Kp:");
    lcd_showstr(16,2,"Kd:");
    lcd_showstr(16,3,"speed_nor:");
    lcd_showstr(16,4,"speed_max:");
    lcd_showstr(16,5,"speed_rod:");
    lcd_showstr(16,6,"advance:");
    lcd_showstr(16,7,"Save");lcd_showstr(112,7,"Cancel");

    sprintf(lcd_buf,"%d", global_param.speed_level + 1);
    lcd_showstr(128,0,lcd_buf);
    sprintf(lcd_buf,"%d", global_param.kp[global_param.speed_level]);
    lcd_showstr(128,1,lcd_buf);
    sprintf(lcd_buf,"%d", global_param.kd[global_param.speed_level]);
    lcd_showstr(128,2,lcd_buf);
    sprintf(lcd_buf,"%d", global_param.speed_normal[global_param.speed_level]);
    lcd_showstr(128,3,lcd_buf);
    sprintf(lcd_buf,"%d", global_param.speed_max[global_param.speed_level]);
    lcd_showstr(128,4,lcd_buf);
    sprintf(lcd_buf,"%d", global_param.speed_round[global_param.speed_level]);
    lcd_showstr(128,5,lcd_buf);
    sprintf(lcd_buf,"%d", global_param.advance);
    lcd_showstr(128,6,lcd_buf);
}

void ui_ElementSet(){
    int8 lcd_buf[6];

    lcd_clear(BLACK);

    lcd_showstr(16,0,"run dir:");
    lcd_showstr(16,1,"Y-I dir:");
    lcd_showstr(16,2,"road_sw:");
    lcd_showstr(16,3,"AUTO_EXP:");
    lcd_showstr(16,4,"GAIN:");
    lcd_showstr(16,5,"/ \\_gain:");
    lcd_showstr(16,6,"||_gain:");

    lcd_showstr(16,7,"Save");lcd_showstr(112,7,"Cancel");


    if(!global_param.run_dir){
        lcd_showstr(128,0,"||");
    }else if(1 == global_param.run_dir){
        lcd_showstr(128,0,"<=");
    }else if(2 == global_param.run_dir){
        lcd_showstr(128,0,"=>");
    }

    if(global_param.Y_dir){
        lcd_showstr(128, 1, "<=");
    }else{
        lcd_showstr(128, 1, "=>");
    }

    if(global_param.road_sw){
        lcd_showstr(128, 2, "ON");
    }else{
        lcd_showstr(128, 2, "OFF");
    }

    if(global_param.AUTO_EXP){
        lcd_showstr(128, 3, "ON");
    }else{
        lcd_showstr(128, 3, "OFF");
    }

    sprintf(lcd_buf,"%2d", global_param.GAIN);
    lcd_showstr(128,4,lcd_buf);
    sprintf(lcd_buf,"%2d", global_param.ramp_s);
    lcd_showstr(128,5,lcd_buf);
    sprintf(lcd_buf,"%2d", global_param.Straight_s);
    lcd_showstr(128,6,lcd_buf);
}

/**
 * @brief  参数设置
 * @param  *variate 需要设置变量的地址
 * @param  step     步进值，即增减一次的大小
 * @param  vlu_max  变量的最大值
 * @return none
 */
void Param_set(void(*p)(void), uint8 *variate, uint8 step, uint8 vlu_max){
    while(TRUE){
        (*p)( );
        lcd_showchar(112,cousor_sub*16,'>');

        key_dir = KEY_NULL;
        while( !(key_dir = key_get()) );

        if(KEY_U == key_dir){
            *variate += step;
            if(*variate > vlu_max)
                *variate = 0;
        }
        else if(KEY_D == key_dir){
            *variate -= step;
            if(*variate > vlu_max)
                *variate = vlu_max;
        }
        else if(KEY_L == key_dir){
            return;
        }
    }
}

void paramet_set(){
    while(TRUE){
        ui_ParametSet();
        key_dir = cursor_show(&cousor_sub, 7);

        if(KEY_R == key_dir){
            switch(cousor_sub){
                case 0: Param_set(ui_ParametSet, &global_param.speed_level, 1, 4);break;
                case 1: Param_set(ui_ParametSet, &global_param.kp[global_param.speed_level], 1, 200);break;
                case 2: Param_set(ui_ParametSet, &global_param.kd[global_param.speed_level], 1, 200);break;
                case 3: Param_set(ui_ParametSet, &global_param.speed_normal[global_param.speed_level], 5, 200);break;
                case 4: Param_set(ui_ParametSet, &global_param.speed_max[global_param.speed_level], 5, 200);break;
                case 5: Param_set(ui_ParametSet, &global_param.speed_round[global_param.speed_level], 5, 200);break;
                case 6: Param_set(ui_ParametSet, &global_param.advance, 1, 200); break;

                case 7: Cancel_save();return;
            }
        }
        else if(KEY_M == key_dir && cousor_sub == 7){
            Param_sto();
            return;
        }
        else
            continue;
    }
}

void element_set(){
    while(TRUE){
        ui_ElementSet();
        key_dir = cursor_show(&cousor_sub, 7);

        if(KEY_R == key_dir){
            switch(cousor_sub){
                case 0:
                    Param_set(ui_ElementSet, &global_param.run_dir, 1, 2);
                    break;
                case 1:
                    Param_set(ui_ElementSet, &global_param.Y_dir, 1, 1);
                    break;
                case 2:
                    Param_set(ui_ElementSet, &global_param.road_sw, 1, 1);
                    break;
                case 3:
                    Param_set(ui_ElementSet, &global_param.AUTO_EXP, 1, 1);
                    break;
                case 4:
                    Param_set(ui_ElementSet, &global_param.GAIN, 1, 64);
                    break;
                case 5:
                    Param_set(ui_ElementSet, &global_param.ramp_s, 5, 80);
                    break;
                case 6:
                    Param_set(ui_ElementSet, &global_param.Straight_s, 5, 80);
                    break;

                case 7:
                    Cancel_save();
                    return;
            }
        }
        else if(KEY_M == key_dir && cousor_sub == 7){
            Param_sto();
            return;
        }
        else
            continue;
    }
}


void ui_home(){
    uint8 run = 0;

    buzzing_ms(300);
    while(!run){
        Param_load();
        first_load = 0;
        if(!global_param.run_dir)
            run_start = 0;

        lcd_clear(BLACK);
        lcd_showstr(12,0,"RUN");
        lcd_showstr(12,1,"ImageDisplay");
        lcd_showstr(12,2,"SetParameter");
        lcd_showstr(12,3,"Element_SW");
        lcd_display_chinese(3 * 16, 5 * 16 + 8, 16, chinese_test[0], 4,BLUE);
        lcd_display_chinese(40,     6 * 16 + 8, 16, Believe_in_the_light[0], 5,GREEN);

        while(KEY_R != cursor_show(&cousor_home, 3));
        switch(cousor_home){
            case 0: lcd_clear(RED);
                    run = 1;break;

            case 1: img_display();
                    pit_disable_interrupt(CCU6_0, PIT_CH0);
                    debug_flag = stopcar = 0;
                    break;
            case 2: paramet_set();break;
            case 3: element_set();break;
        }
    }

    /***延时后使能中断以发车***/
    pit_disable_interrupt(CCU6_0, PIT_CH0);
    pit_disable_interrupt(CCU6_1, PIT_CH0);
    systick_delay_ms(STM0,800);

    pit_enable_interrupt(CCU6_0, PIT_CH0);
    pit_enable_interrupt(CCU6_1, PIT_CH0);
}
